package goliath;

import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.World;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider;
import com.thoughtworks.xstream.converters.javabean.JavaBeanConverter;
import pulpfizz.physics.BodyUtils;
import pulpfizz.physics.Material;
import pulpfizz.pulp.body.BodySprite;
import pulpfizz.pulp.body.Java2DBodySprite;
import pulpfizz.pulp.body.PhysicsLayer;

import java.awt.*;
import java.io.*;
import java.nio.channels.FileChannel;

import goliath.BasicDemo;
import pulpcore.Assets;
import pulpcore.CoreSystem;
import pulpcore.util.Base64;
import pulpcore.util.ByteArray;
import pulpcore.util.StringUtil;
import util.FileHelper;

/**
 * Static methods to help with Body XML serialization.
 * @author will
 * @date Aug 9, 2008 1:58:05 PM
 */
public class XmlUtil {
    public static XStream xs;
    static {
        xs = new XStream();
//        xs.registerConverter(new JavaBeanConverter(xs.getMapper()), XStream.PRIORITY_LOW);
        xs.omitField(Body.class,"m_world");
        xs.omitField(Body.class,"m_prev");
        xs.omitField(Body.class,"m_next");
        xs.omitField(Body.class,"m_contactList");
//        xs.omitField(Body.class,"m_jointList");
//        xs.omitField(org.jbox2d.collision.Shape.class,"m_next");
        xs.omitField(World.class,"m_lock");
        xs.omitField(World.class,"m_contactManager");
        xs.omitField(World.class,"m_broadPhase");
        xs.omitField(World.class,"m_contactList");
//        xs.omitField(NewWorld.class,"m_points");

        xs.registerConverter(new PhysicsConverter());
    }

    /**
     * Serializes a Body into XML.
     * @param b body to save.
     * @return String containing the body XML.
     */
    public static String saveBody(Body b) {
        return xs.toXML(b);
    }

    /**
     * Loads a Body into the specified World.
     * @param bodyXml
     */
    public static void loadBody(String bodyXml, World w) {
        Body b = (Body)xs.fromXML(bodyXml);
        b.m_world = w;
        Body body = BodyUtils.cloneBody(b);
        Material.DEAD_WEIGHT().applyAll(body);
        setBody(body);
    }

    public static BodySprite setBody(Body b) {
        if (b != null) {
            Material m = Material.PLASTIC();
            m.applyAll(b);
            PhysicsLayer layer = BasicDemo.getPhysics();
            Java2DBodySprite myp = new Java2DBodySprite(b, layer, 3, Color.RED, Color.RED);
            layer.add(myp);
            return myp;
        }
        return null;
    }

    public static String savedWorld;

    public static PhysicsLayer loadWorld() {
        try {
            byte[] data = Base64.decode(savedWorld);
            ByteArray b = new ByteArray(data);
            b.decompress();
            String savedWorldDecoded = new String(b.getData(),"UTF-8");
            PhysicsLayer physicsLayer = (PhysicsLayer) xs.fromXML(savedWorldDecoded);
            System.out.println("Loaded world string");
            return physicsLayer;
        } catch (Exception e) {
            System.out.println("Error loading XML data: "+e.getMessage());
            return null;
        }
    }

    public static PhysicsLayer loadWorld(File f) {
        try {
            byte[] worldBytes = FileHelper.getBytes(f);
            savedWorld = new String(worldBytes,"UTF-8");
            return loadWorld();
        } catch (Exception e) {
            System.out.println("Error Loading XML data from file: " + e.getMessage());
            return null;
        }
    }

    public static PhysicsLayer loadWorld(byte[] p) {
        try {
            savedWorld = new String(p,"UTF-8");
        } catch (UnsupportedEncodingException e) {
            System.out.println("Error Loading level data: " + e.getMessage());
            return null;
        }
        return loadWorld();
    }

    public static void saveWorld() {
        try {
            String worldString = xs.toXML(BasicDemo.getPhysics());
            ByteArray b = new ByteArray();
            b.write(worldString.getBytes("UTF-8"));
            b.compress();
            savedWorld = Base64.encode(b.getData());
            System.out.println("Saved world string, length = "+savedWorld.length());
//            System.out.println("World string:"+worldString);
        } catch (Exception e) {
            System.out.println("Error saving XML data: "+e.getMessage());
        }
    }

    public static void saveWorld(File f) {
        saveWorld();
        try {
            OutputStream o = new FileOutputStream(f);
            o.write(savedWorld.getBytes("UTF-8"));
        } catch (Exception e) {
            System.out.println("Error saving XML data to file: " + e.getMessage());
        }
    }

}
